﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace IOExtensions
{
    public class DirectoryStructure
    {
        #region Fields
        public bool _reparseRequired = true;

        private string _path;
        private List<FileInfo> _files;
        private List<DirectoryInfo> _directories;
        private bool _recursive = true;
        #endregion 

        #region Constructor
        public DirectoryStructure(string pathname)
        {
            SetPath(pathname);
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pathname"></param>
        public void SetPath(string pathname)
        {
            if (!String.IsNullOrWhiteSpace(_path))
            {
                if (!_path.ToLower().Equals(pathname.ToLower()))
                {
                    _path = pathname;
                    _reparseRequired = true;
                }
            }
            else
            {
                _path = pathname;
                _reparseRequired = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void Parse()
        {
            if (_path != null)
            {
                if (_files == null)
                {
                    _files = new List<FileInfo>();
                }
                if (_directories == null)
                {
                    _directories = new List<DirectoryInfo>();
                }
                GetFilesRecursive(_path);

                _reparseRequired = false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public IEnumerable<DestinationDirectoryMatch> DirectoryLocations(string path)
        {
            if(_reparseRequired == true)
            {
                Parse();
            }

            foreach (DirectoryInfo directoryInfo in _directories)
            {
                if (!path.Equals(directoryInfo.FullName))
                {
                    string tempName = directoryInfo.FullName.Replace(path, "");
                    tempName = Regex.Replace(tempName, @"^\\", "^", RegexOptions.IgnoreCase);
                    tempName = Regex.Replace(tempName, @"\\", @"[_\s-]+?", RegexOptions.IgnoreCase);
                    tempName = tempName.Replace(" ", @"\s+?");
                    tempName += @"[_\s-]+";

                    DestinationDirectoryMatch directoryMatch = new DestinationDirectoryMatch(directoryInfo.FullName+"\\", tempName);

                    yield return directoryMatch;
                }
            }
        }

        private void GetFilesRecursive(string root)
        {
            Stack<string> dirStack = new Stack<string>();

            dirStack.Push(root);
            _directories.Add(new DirectoryInfo(root));

            while (dirStack.Count > 0)
            {
                string directory = dirStack.Pop();

                try
                {
                    foreach (string file in Directory.GetFiles(directory))
                    {
                        _files.Add(new FileInfo(file));
                    }

                    foreach (string subDirectory in Directory.GetDirectories(directory))
                    {
                        if (Recursive == true)
                        {
                            dirStack.Push(subDirectory);
                        }
                        _directories.Add(new DirectoryInfo(subDirectory));
                    }
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show("Exception occurred parsing files into list - " + ex.Message);
                }
            }
        }

        #region Properties
        public IEnumerable<FileInfo> Files
        {
            get
            {

                if (_reparseRequired == true)
                {
                    Parse();
                }

                return _files;
            }
        }

        public IEnumerable<DirectoryInfo> Directories
        {
            get
            {
                if (_reparseRequired == true)
                {
                    Parse();
                }

                return _directories;
            }
        }

        public bool Recursive
        {
            get
            {
                return _recursive;
            }
            set
            {
                _recursive = value;
            }
        }
        #endregion
    }
}
